package su2010.puz.impl;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.io.Writer;

import su2010.puz.ImageHelper;
import su2010.puz.util.ColorConvert;
import su2010.puz.util.PixelExtractor;

import com.pearsoneduc.ip.op.HistogramException;

public class Histogram implements Cloneable {

	
/////////////////////////////// CONSTANTS ////////////////////////////////


	  private static final String BAND_ERROR = "histogram band not specified";


	  /////////////////////////// INSTANCE VARIABLES ///////////////////////////


	  /**
	   * Number of bands in the source image (1 for greyscale, 3 for colour).
	   */

	  private int bands;

	  /**
	   * Total number of samples processed.
	   */

	  private int samples;

	  /**
	   * 2D array holding frequency data for a greyscale or colour image.
	   */

	  private int[][] freq;

	  /**
	   * 2D array holding cumulative frequency data.
	   */

	  private int[][] cumFreq;

	  /**
	   * Array storing the minimum grey value or minimum R, G and B
	   * values of the source image.
	   */

	  private int[] minValue;

	  /**
	   * Array storing the maximum grey value or maximum R, G and B
	   * values of the source image.
	   */

	  private int[] maxValue;

	  private int[] maxValueIndex;
	  
	  /**
	   * Array storing the lowest frequencies recorded for each
	   * band of the source image.
	   */

	  private int[] minFreq;

	  /**
	   * Array storing the highest frequencies recorded for each
	   * band of the source image.
	   */

	  private int[] maxFreq;
	  

	  /**
	   * Array holding the mean values for each band of the source image.
	   */

	  private double[] meanValue;

	  private int[] hueFreq;
	  
	  private int[][] svFreq;
	  
	  private int[] hueCumFreq;
	  
	  private int[][] svCumFreq;
	  
	  private int[] length;

	  ///////////////////////////// PUBLIC METHODS /////////////////////////////


	  /**
	   * Default constructor.
	   */

	  public Histogram() {
	    allocateStorage();
	  }

	  /**
	   * Constructs a histogram using a Reader as the data source.
	   * @param reader the Reader used to obtain histogram data
	   * @exception IOException if the input data are not formatted correctly.
	   */

	  public Histogram(Reader reader) throws IOException {
	    allocateStorage();
	    read(reader);
	  }

	  /**
	   * Constructs the histogram of a BufferedImage.
	   * @param image the image for which a histogram is required
	   * @exception HistogramException if image is of wrong type.
	   */

	  public Histogram(BufferedImage image) throws HistogramException {
	    allocateStorage();
	    computeHistogram(image);
	  }


	  /**
	   * Clones a histogram.
	   */

	  public Object clone() {
	    Histogram h = new Histogram();
	    if (samples > 0) {
	      h.bands = bands;
	      h.samples = samples;
	      for (int i = 0; i < 4; ++i) {
	        System.arraycopy(freq[i], 0, h.freq[i], 0, 256);
	        System.arraycopy(cumFreq[i], 0, h.cumFreq[i], 0, 256);
	      }
	      System.arraycopy(minFreq, 0, h.minFreq, 0, 4);
	      System.arraycopy(maxFreq, 0, h.maxFreq, 0, 4);
	      System.arraycopy(minValue, 0, h.minValue, 0, 4);
	      System.arraycopy(maxValue, 0, h.maxValue, 0, 4);
	      System.arraycopy(meanValue, 0, h.meanValue, 0, 4);
	    }
	    return h;
	  }


	  /**
	   * Tests for equivalence of Histogram objects.
	   * @return true if histograms contain the same data, false otherwise.
	   */

	  public boolean equals(Object obj) {

	    if (obj instanceof Histogram) {

	      Histogram h = (Histogram) obj;
	      if (bands != h.bands || samples != h.samples)
	        return false;

	      for (int k = 0; k < 256; ++k)
	        for (int j = 0; j < bands; ++j)
	          if (freq[j][k] != h.freq[j][k])
	            return false;

	      // Don't need to check contents of other arrays, since
	      // they are derived from frequency data...

	      return true;

	    }
	    else
	      return false;

	  }


	  /**
	   * @return a String object giving the number of bands and samples
	   *   in the histogram.
	   */

	  public String toString() {
	    return new String(getClass().getName() + ": " +
	     bands + " bands, " + samples + " samples");
	  }


	  /**
	   * Calculates histogram data for a BufferedImage.
	   * @param image BufferedImage for which a histogram is required
	   * @exception HistogramException if the image is of an unsupported type.
	   */

	  public void computeHistogram(BufferedImage image)
	   throws HistogramException {

	    initialize();   // zero arrays before accumulating frequency data

	    if (image.getType() == BufferedImage.TYPE_BYTE_GRAY)
	      bands = 1;
	    else
	      bands = 4;

	    samples = image.getWidth()*image.getHeight();
	    if (samples > 0) {
	      accumulateFrequencies(image);
	      computeStatistics();
	    }

	  }


	  /**
	   * Reads histogram data from the specified source.
	   * @param source Reader used to obtain histogram data
	   * @exception IOException if the input data are not formatted correctly.
	   */

	  public void read(Reader source) throws IOException {

	    BufferedReader in = new BufferedReader(source);
	    String line = in.readLine();

	    initialize();
	    if (line.equals("# grey histogram")) {       // one value per line
	      bands = 1; 
	      samples = 0;
	      for (int i = 0; i < 256; ++i) {
	        freq[0][i] = Integer.parseInt(in.readLine());
	        samples += freq[0][i];
	      }
	      if (samples > 0)
	        computeStatistics();
	    }
	    else if (line.equals("# RGB histogram")) {   // three values per line
	      bands = 4;
	      samples = 0;
	      StreamTokenizer tok = new StreamTokenizer(in);
	      for (int k = 0; k < 256; ++k) {
	        for (int j = 0; j < 4; ++j) {
	          tok.nextToken();
	          if (tok.ttype == StreamTokenizer.TT_EOF)
	            throw new EOFException("histogram appears to be truncated");
	          if (tok.ttype == StreamTokenizer.TT_NUMBER)
	            freq[j][k] = (int) tok.nval;
	        }
	        samples += freq[0][k];
	      }
	      if (samples > 0)
	        computeStatistics();
	    }
	    else
	      throw new IOException("invalid histogram file");

	  }


	  /**
	   * Writes histogram data to the specified destination.
	   * @param destination Writer used to output histogram data
	   */

	  public void write(Writer destination) {
	    PrintWriter out =
	     new PrintWriter(new BufferedWriter(destination));
	    if (sourceIsGrey()) {
	      out.println("# grey histogram");
	      for (int i = 0; i < 256; ++i)
	        out.println(freq[0][i]);         // no special formatting
	    }
	    else {
	      out.println("# RGB histograms");
	      for (int k = 0; k < 256; ++k) {
	        for (int j = 0; j < 4; ++j)
	          writeValue(freq[j][k], out);   // right-justified frequencies,
	        out.println();                   // three values per line
	      }
	    }
	    out.flush();
	  }


	  /**
	   * Writes cumulative histogram data to the specified destination.
	   * @param destination Writer used to output data
	   */

	  public void writeCumulative(Writer destination) {
	    PrintWriter out =
	     new PrintWriter(new BufferedWriter(destination));
	    if (sourceIsGrey()) {
	      out.println("# grey cumulative histogram");
	      for (int i = 0; i < 256; ++i)
	        out.println(cumFreq[0][i]);         // no special formatting
	    }
	    else {
	      out.println("# RGB cumulative histograms");
	      for (int k = 0; k < 256; ++k) {
	        for (int j = 0; j < 4; ++j)
	          writeValue(cumFreq[j][k], out);   // right-justified frequencies,
	        out.println();                      // three values per line
	      }
	    }
	    out.flush();
	  }


	  /**
	   * Indicates whether histogram was computed from a greyscale image or not.
	   * @return true if source is a greyscale image, false otherwise.
	   */

	  public boolean sourceIsGrey() {
	    return bands == 1;
	  }


	  /**
	   * Gives number of histogram bands.
	   * @return number of bands, as an integer (1 if the source of the
	   *   histogram is a greyscale image, 4 if the source is a colour image).
	   */

	  public int getNumBands() {
	    return bands;
	  }


	  /**
	   * Gives number of samples taken from source image.
	   * @return number of samples, as an integer.
	   */

	  public int getNumSamples() {
	    return samples;
	  }


	  /**
	   * Retrieves the frequency of occurrence of a specified grey level.
	   * @param value pixel value for which a frequency is required
	   * @return frequency as an integer (0 or greater).
	   * @exception HistogramException if source is not a greyscale image.
	   */

	  public int getFrequency(int value) throws HistogramException {
	    if (sourceIsGrey())
	      return freq[0][value];
	    else
	      throw new HistogramException(BAND_ERROR);
	  }

	  /**
	   * Retrieves the frequency of occurrence of a particular value
	   *  in a given band.
	   * @param band band for which a frequency is required (0, 1 or 2)
	   * @param value pixel value for which a frequency is required
	   * @return frequency as an integer (0 or greater).
	   */

	  public int getFrequency(int band, int value) {
	    return freq[band][value];
	  }


	  /**
	   * Retrieves the frequency of occurrence of a grey level less than
	   *  or equal to the specified value.
	   * @param value pixel value for which a cumulative frequency is required
	   * @return cumulative frequency as an integer (0 or greater).
	   * @exception HistogramException if source is not a greyscale image.
	   */

	  public int getCumulativeFrequency(int value) throws HistogramException {
	    if (sourceIsGrey())
	      return cumFreq[0][value];
	    else
	      throw new HistogramException(BAND_ERROR);
	  }

	  /**
	   * Retrieves the frequency of occurrence of values less than or
	   *  equal to the specified value in a given band.
	   * @param band band for which a cumulative frequency is required
	   * @param value pixel value for which a cumulative frequency is required
	   * @return cumulative frequency as an integer (0 or greater).
	   */

	  public int getCumulativeFrequency(int band, int value) {
	    return cumFreq[band][value];
	  }


	  /**
	   * Gives the smallest frequency recorded in the histogram.
	   * @return minimum frequency as an integer (0 or greater).
	   * @exception HistogramException if source is not a greyscale image.
	   */

	  public int getMinFrequency() throws HistogramException {
	    if (sourceIsGrey())
	      return minFreq[0];
	    else
	      throw new HistogramException(BAND_ERROR);
	  }

	  /**
	   * Gives the smallest frequency recorded in the histogram.
	   * @param band band for which a minimum frequency is required (0, 1 or 2)
	   * @return minimum frequency in that band, as an integer (0 or greater).
	   */

	  public int getMinFrequency(int band) {
	    return minFreq[band];
	  }


	  /**
	   * Gives the largest frequency recorded in the histogram.
	   * @return maximum frequency as an integer (0 or greater).
	   * @exception HistogramException if source is not a greyscale image.
	   */

	  public int getMaxFrequency() throws HistogramException {
	    if (sourceIsGrey())
	      return maxFreq[0];
	    else
	      throw new HistogramException(BAND_ERROR);
	  }

	  public int getPeakValue(int band) {
		  return maxValueIndex[band];
	  }
	  
	  public int getColorLength(int band){
		  return length[band];
	  }
	  /**
	   * Gives the largest frequency recorded in the histogram.
	   * @param band band from which maximum frequency is required (0, 1 or 2)
	   * @return maximum frequency in that band, as an integer (0 or greater).
	   */

	  public int getMaxFrequency(int band) {
	    return maxFreq[band];
	  }


	  /**
	   * Gives minimum value for which counts have been recorded.
	   * @return minimum value as an integer (0 or greater).
	   * @exception HistogramException if source is not a greyscale image.
	   */

	  public int getMinValue() throws HistogramException {
	    if (sourceIsGrey())
	      return minValue[0];
	    else
	      throw new HistogramException(BAND_ERROR);
	  }

	  /**
	   * Gives minimum value for which counts have been recorded
	   * in the specified band.
	   * @param band band for which a minimum value is required (0, 1 or 2)
	   * @return minimum value in that band, as an integer (0 or greater).
	   */

	  public int getMinValue(int band) {
	    return minValue[band];
	  }


	  /**
	   * Gives maximum value for which counts have been recorded.
	   * @return maximum value, as an integer (0 or greater).
	   * @exception HistogramException if source is not a greyscale image.
	   */

	  public int getMaxValue() throws HistogramException {
	    if (sourceIsGrey())
	      return maxValue[0];
	    else
	      throw new HistogramException(BAND_ERROR);
	  }

	  /**
	   * Gives maximum value for which counts have been recorded
	   * in the specified band.
	   * @param band the band for which maximum value is required (0, 1 or 2)
	   * @return maximum value in that band, as an integer (0 or greater).
	   */

	  public int getMaxValue(int band) {
	    return maxValue[band];
	  }


	  /**
	   * Gives mean value of a greyscale histogram.
	   * @return mean value, as a double-precision real number.
	   * @exception HistogramException if source is not a greyscale image.
	   */

	  public double getMeanValue() throws HistogramException {
	    if (sourceIsGrey())
	      return meanValue[0];
	    else
	      throw new HistogramException(BAND_ERROR);
	  }

	  /**
	   * Gives mean value in one band of a colour histogram.
	   * @param band the band for which mean value is required (0, 1 or 2)
	   * @return mean value in the specified band, as a double-precision
	   *   real number.
	   */

	  public double getMeanValue(int band) {
	    return meanValue[band];
	  }


	  /////////////////////////// NON-PUBLIC METHODS ////////////////////////////


	  /**
	   * Allocates storage for arrays.
	   */

	  private void allocateStorage() {
	    freq = new int[4][256];
	    cumFreq = new int[4][256];
	    hueFreq = new int[361];
	    svFreq = new int[2][101];
	    hueCumFreq = new int[361];
	    svCumFreq = new int[2][101];
	    minValue = new int[7];
	    maxValue = new int[7];
	    minFreq = new int[7];
	    maxFreq = new int[7];
	    meanValue = new double[7];
	    maxValueIndex = new int[7];
	    length = new int[7];
	  }


	  /**
	   * Initializes arrays and other instance variables properly.
	   */

	  private void initialize() {
	    bands = samples = 0;
	    for (int i = 0; i < 4; ++i)
	      for (int j = 0; j < 256; ++j){
	        freq[i][j] = cumFreq[i][j] = 0;
	        if(i<2 && j<101)
		    	svFreq[i][j] = svCumFreq[i][j] = 0;
	      }
	    for(int j = 0; j<361;j++)
	    	hueFreq[j] = hueCumFreq[j] = 0;
	    for (int i = 0; i < 7; ++i) {
	      minValue[i] = maxValue[i] = maxValueIndex[i] = 0;
	      minFreq[i] = maxFreq[i] = 0;
	      meanValue[i] = 0.0;
	    }
	    length[0] = length[1] = length[2] = length[3] = 255;
	    length[4] = 360;
	    length[5] = length[6] = 100;
	  }


	  /**
	   * Accumulates histogram data by retrieving pixel values
	   * from the specified image.
	   * @param image BufferedImage for which a histogram must be calculated
	   * @exception HistogramException if the image type is not supported.
	   */

	  private void accumulateFrequencies(BufferedImage image)
	   throws HistogramException {

	    if (image.getType() == BufferedImage.TYPE_BYTE_BINARY
	     || image.getType() == BufferedImage.TYPE_USHORT_GRAY)
	      throw new HistogramException("invalid image type");

	    Raster raster = image.getRaster();
	    if (image.getType() == BufferedImage.TYPE_BYTE_GRAY) {
	      for (int y = 0; y < image.getHeight(); ++y)
	        for (int x = 0; x < image.getWidth(); ++x)
	          ++freq[0][raster.getSample(x, y, 0)];
	    }
	    else {
	      int[] value = new int[3];
	      for (int y = 0; y < image.getHeight(); ++y)
	        for (int x = 0; x < image.getWidth(); ++x) {
	          raster.getPixel(x, y, value);
	          ++freq[0][value[0]];
	          ++freq[1][value[1]];
	          ++freq[2][value[2]];
	        }
	      for(int i = 0 ; i < 256; i++)
	    	  freq[3][i] = Math.round(0.2126f*freq[0][i] + 0.7152f*freq[1][i] + 0.0722f*freq[2][i]);
	    }
	    int[][][] hsv = PixelExtractor.getHSV(image);
	    for(int x = 0; x<hsv.length; x++)
	    	for(int y = 0 ; y<hsv[0].length; y++){
	    		++hueFreq[hsv[x][y][0]];
	    		++svFreq[0][hsv[x][y][1]];
	    		++svFreq[1][hsv[x][y][2]];
	    	}
	  }


	  /**
	   * Computes statistics from histogram data.
	   */

	  private void computeStatistics() {

	    int i, j;
	      
	    for (i = 0; i < bands; ++i) {

	      // Compute cumulative histogram

	      cumFreq[i][0] = freq[i][0];
	      for (j = 1; j < 256; ++j)
	        cumFreq[i][j] = cumFreq[i][j-1] + freq[i][j];
	      
	      // Find minimum value

	      for (j = 0; j < 256; ++j) {
	        if (freq[i][j] > 0) {
	          minValue[i] = j;
	          break;
	        }
	      }

	      // Find maximum value

	      for (j = 255; j >= 0; --j) {
	        if (freq[i][j] > 0) {
	          maxValue[i] = j;
	          break;
	        }
	      }

	      // Find lowest and highest frequencies, and determine mean

	      minFreq[i] = Integer.MAX_VALUE;
	      for (j = 0; j < 256; ++j) {
	        if (freq[i][j] < minFreq[i])
	          minFreq[i] = freq[i][j];
	        else if (freq[i][j] > maxFreq[i]){
	          maxFreq[i] = freq[i][j];
	          maxValueIndex[i] = j;
	        }
	        meanValue[i] += (double) (j*freq[i][j]);
	      }
	      meanValue[i] /= (double) samples;

	    }
	    
	    hueCumFreq[0] = hueFreq[0];
	    for (j = 1; j < 361; j++)
	    	  hueCumFreq[j] = hueCumFreq[j-1] + hueFreq[j];

	    for (j = 0; j < 361; ++j) {
	        if (hueFreq[j] > 0) {
	          minValue[i] = j;
	          break;
	        }
	      }
	    
	    for (j = 360; j >= 0; --j) {
	        if (hueFreq[j] > 0) {
	          maxValue[i] = j;
	          break;
	        }
	      }
	    
	    minFreq[i] = Integer.MAX_VALUE;
	      for (j = 0; j < 361; ++j) {
	        if (hueFreq [j]< minFreq[i])
	          minFreq[i] = hueFreq[j];
	        else if (hueFreq[j] > maxFreq[i]){
	          maxFreq[i] = hueFreq[j];
	          maxValueIndex[i] = j;
	        }
	        meanValue[i] += (double) (j*hueFreq[j]);
	      }
	      meanValue[i] /= (double) samples;
	      
	    for(i = 0; i < 2; i++){
		    svCumFreq[0] = svFreq[0];
		    for (j = 1; j < 101; j++)
		    	  svCumFreq[i][j] = svCumFreq[i][j-1] + svFreq[i][j];

		    for (j = 0; j < 101; ++j) {
		        if (svFreq[i][j] > 0) {
		          minValue[5+i] = j;
		          break;
		        }
		      }
		    
		    for (j = 100; j >= 0; --j) {
		        if (svFreq[i][j] > 0) {
		          maxValue[5+i] = j;
		          break;
		        }
		      }
		    
		    minFreq[5+i] = Integer.MAX_VALUE;
		      for (j = 0; j < 101; ++j) {
		        if (svFreq[i][j]< minFreq[5+i])
		          minFreq[5+i] = svFreq[i][j];
		        else if (svFreq[i][j] > maxFreq[5+i]){
		          maxFreq[5+i] = svFreq[i][j];
		          maxValueIndex[5+i] = j;
		        }
		        meanValue[5+i] += (double) (j*svFreq[i][j]);
		      }
		      meanValue[5+i] /= (double) samples;
	    }
	  }


	  /**
	   * Outputs an integer in right-justified form.
	   * @param value integer value to be formatted
	   * @param out destination for the formatted value
	   */

	  private void writeValue(int value, PrintWriter out) {
	    if (value > 99999)
	      out.print(" " + value);
	    else if (value > 9999)
	      out.print("  " + value);
	    else if (value > 999)
	      out.print("   " + value);
	    else if (value > 99)
	      out.print("    " + value);
	    else if (value > 9)
	      out.print("     " + value);
	    else
	      out.print("      " + value);
	  }

	  //////////////////Public metode added by stef//////////////
		public int[] getHistogram(int color) {
			if(color<4){
				return freq[color];
			}
			else if(color == 4){
				return hueFreq;
			}
			else{
				return svFreq[color-5];
			}
		}
		
		public void showHistogram(int color, String title){
			int[] hist = getHistogram(color);
			BufferedImage bufferedImage = new BufferedImage(256,
					256, BufferedImage.TYPE_INT_RGB);
			Graphics g = bufferedImage.createGraphics();
			double scale = (256 / (double)getMaxFrequency(color));
		    if(color == ImageHelper.RED)
		    	g.setColor(Color.red);
		    if(color == ImageHelper.BLUE)
		    	g.setColor(Color.blue);
		    if(color == ImageHelper.GREEN)
		    	g.setColor(Color.green);
		    if(color == ImageHelper.LUMINANCE)
		    	g.setColor(Color.yellow);
		    for (int x = 0; x < 256; ++x) {
		      int y = (int) Math.round(scale*hist[x]);
		      if (y > 0)
		        g.drawLine(x, 256, x, 256-y);
		    }
		    g.dispose();
		    ImageHelper.showImage(bufferedImage, "histogram "+title);
		}
		
		public void showHistogram(int[] histogram, int color, String title){
			BufferedImage bufferedImage = new BufferedImage(256,
					256, BufferedImage.TYPE_INT_RGB);
			Graphics g = bufferedImage.createGraphics();
			double scale = (256 / (double)getMaxFrequency(color));
			if(color == ImageHelper.RED)
		    	g.setColor(Color.red);
		    if(color == ImageHelper.BLUE)
		    	g.setColor(Color.blue);
		    if(color == ImageHelper.GREEN)
		    	g.setColor(Color.green);
		    if(color == ImageHelper.LUMINANCE)
		    	g.setColor(Color.yellow);
		    for (int x = 0; x < histogram.length; ++x) {
		      int y = (int) Math.round(scale*histogram[x]);
		      if (y > 0)
		        g.drawLine(x, histogram.length, x, histogram.length-y);
		    }
		    g.dispose();
		    ImageHelper.showImage(bufferedImage, "smoothed histogram "+title);
		}
		
		public void showHueHistogram(int X, int Y){
			BufferedImage image = new BufferedImage(361,256,BufferedImage.TYPE_INT_RGB);
			Graphics g = image.createGraphics();
			double scale = (256 / (double)getMaxFrequency(4));
			for(int x = 0; x < 361; x++){
				g.setColor(getColor(x));
				int y = (int) Math.round(scale*hueFreq[x]);
				if(y > 0)
					g.drawLine(x, 256, x, 256-y);
			}
			g.dispose();
			ImageHelper.showImage(X, Y, image, "histogram hue");
		}
		
		public Color getColor(int x){
			int color = ColorConvert.hsv2rgb(x/360f, 1f, 1f);
			return new Color(color);
		}
		
		public void showHistogram(int X, int Y, int color, String title){
			int[] hist = getHistogram(color);
			BufferedImage bufferedImage = new BufferedImage(hist.length,
					256, BufferedImage.TYPE_INT_RGB);
			Graphics g = bufferedImage.createGraphics();
			double scale = (256 / (double)getMaxFrequency(color));
		    if(color == ImageHelper.RED)
		    	g.setColor(Color.red);
		    if(color == ImageHelper.BLUE)
		    	g.setColor(Color.blue);
		    if(color == ImageHelper.GREEN)
		    	g.setColor(Color.green);
		    if(color == ImageHelper.LUMINANCE)
		    	g.setColor(Color.yellow);
		    if(color == ImageHelper.VALUE)
		    	g.setColor(Color.ORANGE);
		    if(color == ImageHelper.SATURATION)
		    	g.setColor(Color.PINK);
		    for (int x = 0; x < hist.length; ++x) {
		      int y = (int) Math.round(scale*hist[x]);
		      if (y > 0)
		        g.drawLine(x, 256, x, 256-y);
		    }
		    g.dispose();
		    ImageHelper.showImage(X, Y, bufferedImage, "histogram "+title);
		}
	
		/**
		 * prikazuje histograme crvene, zelene, plave boje, i luminancea.
		 */
		public void showHistograms(){
			int x = 200;
			int y = 100;
			showHistogram(x, y, ImageHelper.RED, "red");
			showHistogram(x+280, y, ImageHelper.GREEN, "green");
			showHistogram(x, y+300, ImageHelper.BLUE, "blue");
			showHistogram(x+280, y+300, ImageHelper.LUMINANCE, "luminence");
			showHueHistogram(x+840, y+200);
			showHistogram(x+560, y,ImageHelper.SATURATION,"saturation");
			showHistogram(x+560, y+300, ImageHelper.VALUE, "value");
		}
}
